package com.dxp.plugins;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apache.database.datasource.ConnctionData;
import com.apache.exception.BusinessException;
import com.apache.ius.able.ScheduledExecutor;
import com.apache.ius.common.CommonUtils;
import com.apache.ius.plugin.CustomMethodPlugin;
import com.apache.tools.DataMap;
import com.apache.tools.DateUtils;
import com.apache.tools.StrUtil;
import com.dxp.utils.HttpService;
import com.dxp.utils.ScriptEngineUtil;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryManager;
import com.netflix.discovery.shared.Application;
import org.apache.log4j.Logger;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

/**
 * @description: 数据采集
 * @author: Hou Dayu
 * @date: Created in 2020/7/20
 */
public class DataBathCollectionPluginImpl implements CustomMethodPlugin {

    protected Logger log = Logger.getLogger("DataCollection");

    private String reqUrls = "qryEnterpriseBasicInformation,listOfBusinessExceptions,taxRegistrationInformation,legalBlackList,legalRedList,administrativePenaltyInformation,seriousIllegalAndDishonestEnterprises,getBusinessLicense,exchangeAdministrativePenalties,exchangeAdministrativeLicense,ccppQueryDetail" +
            ",queryListAbnormal";
    @Override
    public Object beforeInvoke(Map<String, Object> map) {
        String isStatistical = StrUtil.doNull(String.valueOf(map.get("dataType")),"F");//是否统计
        if("T".equals(isStatistical)){
            String sysEname = String.valueOf(map.get("sysEname"));
            if(StrUtil.isNull(sysEname)) {
                dataStatistical(map);//采集统计
            } else {
                getDxp(map);
            }
        }  else {
            String interfaceCode = String.valueOf(map.get("interfaceCode"));
            List<String> arrays  = Arrays.asList(reqUrls.split(","));
            if(arrays.contains(interfaceCode)){
                dataCollection(map);
                if(!map.containsKey(CustomMethodPlugin.resultMark)) {
                    map.put(CustomMethodPlugin.resultMark, "接口已进入异步采集阶段，耗时可能可会比较长，请稍后进行查询采集结果");
                }
            } else {
                map.put(CustomMethodPlugin.resultMark,"暂不支持此接口进行批量数据采集");
            }
        }
        return null;
    }

    private void getDxp(Map<String, Object> map){
        Map data = new HashMap();
        List dwList = select("dxp","select count(sys_ename) num,sys_ename,sys_cname from (select ir.user_owner sys_ename,reg.sys_cname from dx_sys_reg reg left JOIN dx_interface_reg ir on ir.sys_ename=reg.sys_ename  where ir.del_status='F')tt  group by sys_ename,sys_cname order by num desc");
        if(!dwList.isEmpty()) {
            List list = new ArrayList();
            long total = 0;
            List<String> dws = new ArrayList();
            for(int i=0;i<dwList.size();i++){
                DataMap<String> dm = (DataMap)dwList.get(i);
                if(StrUtil.isNotNull(dm.get("sysEname")) && !dws.contains(dm.get("sysEname"))) {
                    dws.add(dm.get("sysEname"));
                }
                total += Long.valueOf(dm.get("num"));
                list.add(dm);
            }
            data.put("datas", list);
            data.put("total", total);
            data.put("dwTotal", dws.size());
        }
        Map datas = new HashMap();
        datas.put("dxpData",data);
        map.put(CustomMethodPlugin.resultMark, "T");
        map.put(CustomMethodPlugin.pluginInnerReturn, datas);
    }

    /**
     * 按指定接口进行数据采集
     */
    private void dataCollection(Map<String, Object> map) {
        String requestUrl = String.valueOf(map.get("requestUrl"));
        String interfaceCode = String.valueOf(map.get("interfaceCode"));
        if(StrUtil.isNull(requestUrl) || StrUtil.isNull(interfaceCode)){
            //throw new BusinessException("参数requestUrl或interfaceCode不能为空");
            map.put(CustomMethodPlugin.resultMark,"参数requestUrl或interfaceCode不能为空");
            return ;
        }
        String serverUrl = getRequestUrl("");
        if (StrUtil.isNull(serverUrl)) {
            log.warn("RECEIVE-SERVER服务已下线");
            map.put(CustomMethodPlugin.resultMark,"数据采集(RECEIVE-SERVER)服务已下线");
            return;
            //throw new BusinessException("数据采集(RECEIVE-SERVER)服务已下线");
        }
        final String manaType = StrUtil.doNull(String.valueOf(map.get("manaType")), "DEC");
        ScheduledExecutor.instance().runable(new Runnable() {
            @Override
            public void run() {
                if ("ccppQueryDetail".equals(interfaceCode)) {
                    ccppServerData(requestUrl,manaType);//中国海关企业进出口信用信息公示平台详情接口
                } else if("queryListAbnormal".equals(interfaceCode)) {
                    String bodyStr = resultBody(interfaceCode);
                    String url = serverUrl + (requestUrl.startsWith("/receive") ? requestUrl : "receive" + requestUrl);
                    url = url.replaceAll("/receive/receive/","/receive/");
                    System.out.println(url);
                    HttpService.sendHttp(url, "post", null, bodyStr, "json");
                } else {
                    List<Map> orgs = null;
                    try {
                        Connection con = ConnctionData.getInstance().getConnection("crm");
                        orgs = ConnctionData.getInstance().selectListInfo(con, "select org_ename, org_cname from uct_org where org_type='ENT'");
                    } catch (SQLException e) {
                    }
                    if (!StrUtil.isEmpty(orgs)) {
                        for (Map<String, String> org : orgs) {
                            String orgEname = org.get("orgEname");
                            if (StrUtil.isNull(orgEname) || orgEname.length() < 10) {
                                continue;
                            }
                            String bodyStr = resultBody(interfaceCode).replace("#orgEname#", orgEname);
                            String url = serverUrl + (requestUrl.startsWith("/receive") ? requestUrl : "receive" + requestUrl);
                            HttpService.sendHttp(url, "post", null, bodyStr, "json");
                        }
                    }
                }
            }
        });
    }

    /**
     * 统计查询
     */
    private void dataStatistical(Map<String, Object> map) {
        String interfaceCode = String.valueOf(map.get("interfaceCode"));
        String searchRows = StrUtil.doNull(String.valueOf(map.get("rows")),"20");
        if(StrUtil.isNull(interfaceCode)){
            map.put(CustomMethodPlugin.resultMark,"参数interfaceCode不能为空");
            return ;
        }
        String serverUrl = getSearchServerCtxByConfig();
        if (StrUtil.isNull(serverUrl)) {
            map.put(CustomMethodPlugin.resultMark,"统一查询(SEARCH-SERVER)服务已下线");
            return;
        }
        String gteStr = String.valueOf(map.get("gte"));
        String dateStr = StrUtil.doNull(gteStr, DateUtils.Now.fmt_yyyyMMdd());
        final long gte = DateUtils.strToLong(dateStr + " 00:00:00", DateUtils.FmtStr.yyyyMMdd_HHmmss);
        if("all".equals(interfaceCode)){
            String esSql = "{\"size\": 0,\"aggs\": {\"2\": {\"terms\": {\"field\": \"interfaceCode\",\"size\": "+searchRows+"}}},\"stored_fields\": [\"*\"],\"docvalue_fields\": [\"createdTime\"]," +
                    "\"query\": {\"bool\": {\"must\": [{\"match_all\": {}},{" +
                    "\"range\": {\"createdTime\": {\"gte\": "+gte+"," +
                    "\"format\": \"epoch_millis\"}}}]}}}";
            String result = HttpService.sendHttp(serverUrl + "/statisticsByQuery/depositcertificate?indexType=doc", "post", null, esSql, "json");
            if(StrUtil.isNotNull(result)) {
                JSONObject json = JSON.parseObject(result);
                if ("T".equals(json.getString("flag"))) {
                    map.put(CustomMethodPlugin.resultMark, "T");
                    map.put(CustomMethodPlugin.pluginInnerReturn, json.get("data"));
                    return;
                }
            }
            map.put(CustomMethodPlugin.resultMark,"获取统计数据失败");
            return;
        } else {
            try {
                //存证统计
                String esdeposit = "{\"size\": 0,\"stored_fields\": [\"*\"],\"docvalue_fields\": [\"createdTime\"]," +
                        "\"query\": {\"bool\": {\"must\": [{\"match_all\": {}}," +
                        "{\"match_phrase\": {\"interfaceCode\": {\"query\": \"" + interfaceCode + "\"}}}," +
                        "{\"range\": {\"createdTime\": {\"gte\": " + gte + ",\"format\": \"epoch_millis\"}}}" +
                        "]}}}";
                String deposit = HttpService.sendHttp(serverUrl + "/statisticsByQuery/depositcertificate?indexType=doc", "post", null, esdeposit, "json");
                //解析统计
                String esanalyze = "{\"size\": 0,\"aggs\": {\"2\": {\"terms\": {\"field\": \"traceId\",\"size\": 5,\"order\": {\"_count\": \"desc\"}}}},\"stored_fields\": [\"*\"],\"docvalue_fields\": [\"createdTime\"]," +
                        " \"query\": {\"bool\": {\"must\": [{\"match_all\": {}}," +
                        " {\"match_phrase\": {\"interfaceCode\": {\"query\": \"" + interfaceCode + "\"}}}," +
                        " {\"range\": {\"createdTime\": {\"gte\": " + gte + ",\"format\": \"epoch_millis\"}}}" +
                        "]}} }";
                String analyze = HttpService.sendHttp(serverUrl + "/statisticsByQuery/dataanalyze?indexType=doc", "post", null, esanalyze, "json");
                JSONObject jsonAnalyze = JSON.parseObject(analyze);
                if ("T".equals(jsonAnalyze.getString("flag"))) {
                    JSONArray jsons = jsonAnalyze.getJSONArray("data");
                    for (int i = 0; i < jsons.size(); i++) {
                        JSONObject obj = jsons.getJSONObject(i);
                        obj.remove("keyAsString");
                        obj.remove("name");
                    }
                }
                Map<String, Object> data = new HashMap();
                if (StrUtil.isNotNull(deposit)) {
                    JSONObject jsonDeposit = JSON.parseObject(deposit);
                    data.put("depositcertificate", jsonDeposit);//接口调用次数
                }
                if (jsonAnalyze != null) {
                    System.out.println("result2=" + jsonAnalyze.toJSONString());
                    data.put("dataanalyze", jsonAnalyze);
                }
                map.put(CustomMethodPlugin.resultMark, "T");
                map.put(CustomMethodPlugin.pluginInnerReturn, data);
            } catch (Exception e) {
                map.put(CustomMethodPlugin.resultMark, "数据统计查询出错，请重试");
                return;
            }
        }
    }

    /**
     * 获取查询服务：根据系统版本模式：0/空=全版（默认 走hbase+searchServer），1=简版（不走hbase)
     * @return
     */
    private String getSearchServerCtxByConfig(){
        String sys_version_mode = StrUtil.doNull(CommonUtils.getConfigVal("sys_version_mode"), "0");
        String dataSendServer = "",dataServerName = "SEARCH-SERVER";
        if("0".equals(sys_version_mode)){
            dataSendServer = getRequestUrl("SEARCH-SERVER");
        }else{
            dataSendServer = getRequestUrl("RECEIVE-SERVER");
            dataServerName = "RECEIVE-SERVER";
        }
        log.info("config.sys_version_mode：["+sys_version_mode+"]["+dataServerName+"]->"+dataSendServer);
        return dataSendServer;
    }

    private String resultBody(String interfaceCode){
        StringBuilder sb = new StringBuilder();
        switch (interfaceCode){
            case "qryEnterpriseBasicInformation":
                sb.append("{\"UNI_BSS_ATTACHED\": \"\",\"UNI_BSS_BODY\": {");
                sb.append("\"QRY_ENTERPRISE_BASIC_INFORMATION_REQ\": {\"tyxydm\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "listOfBusinessExceptions":
                sb.append("{\"UNI_BSS_ATTACHED\": \"\",\"UNI_BSS_BODY\": {");
                sb.append("\"LIST_OF_BUSINESS_EXCEPTIONS_REQ\": {\"tyxydm\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "taxRegistrationInformation":
                sb.append("{\"UNI_BSS_ATTACHED\": \"\",\"UNI_BSS_BODY\": {");
                sb.append("\"TAX_REGISTRATION_INFORMATION_REQ\": {\"keyname\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "legalBlackList":
                sb.append("{\"UNI_BSS_ATTACHED\": \"\",\"UNI_BSS_BODY\": {");
                sb.append("\"LEGAL_BLACK_LIST_REQ\": {\"xy10101002\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "legalRedList":
                sb.append("{\"UNI_BSS_ATTACHED\": \"\",\"UNI_BSS_BODY\": {");
                sb.append("\"LEGAL_RED_LIST_REQ\": {\"xy10101002\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "administrativePenaltyInformation":
                sb.append("{\"UNI_BSS_ATTACHED\": \"\",\"UNI_BSS_BODY\": {");
                sb.append("\"ADMINISTRATIVE_PENALTY_INFORMATION_REQ\": {\"tyshxydm\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "seriousIllegalAndDishonestEnterprises":
                sb.append("{\"UNI_BSS_ATTACHED\": \"\",\"UNI_BSS_BODY\": {");
                sb.append("\"SERIOUS_ILLEGAL_AND_DISHONEST_ENTERPRISES_REQ\": {\"uniscid\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "getBusinessLicense":
                sb.append("{\"UNI_BSS_ATTACHED\": {\"MEDIA_INFO\": \"\"},\"UNI_BSS_BODY\": {");
                sb.append("\"GET_BUSINESS_LICENSE_REQ\": {\"type\": \"0\",\"value\": \"#orgEname#\"}");
                sb.append(" },\"UNI_BSS_HEAD\": {\"APP_ID\": \"QtlGk8hCJE\",\"TIMESTAMP\": \"\",\"TRANS_ID\": \"\",\"TOKEN\": \"\" }}");
                break;
            case "exchangeAdministrativePenalties":
                sb.append("{\"detailsInterfaceUri\": \"http://www.safe.gov.cn/www/illegal/listQuery?saffno=\",\"tyxydm\": \"#orgEname#\"}");
                break;
            case "exchangeAdministrativeLicense":
                sb.append("{\"shcode\": \"#orgEname#\",\"govName\": \"\"}");
                break;
            case "queryListAbnormal":
                sb.append("{\"curPage\": \"1\",\"apanage\": \"610000\",\"depCodeChg\": \"\",\"pageSize\": \"20\"}");
                break;
        }
        return sb.toString();
    }

    private String getRequestUrl(String serviceId){
        serviceId = StrUtil.doNull(serviceId,"RECEIVE-SERVER");
        DiscoveryManager discoveryClient = DiscoveryManager.getInstance();
        Application app = discoveryClient.getEurekaClient().getApplication(serviceId);
        if(app != null) {
            int dszie = app.getInstances().size();
            if (dszie > 0) {
                InstanceInfo instances = null;
                if(dszie > 1) {
                    Random rand = new Random();
                    instances = app.getInstances().get(rand.nextInt(dszie));
                } else {
                    instances = app.getInstances().get(0);
                }
                return instances.getHomePageUrl();
            }
        }
        return "";
    }

    @Override
    public Object doInvoke(Map<String, Object> map) {
        return null;
    }

    @Override
    public Object afterInvoke(Map<String, Object> map) {
        return null;
    }

    private void ccppServerData(String requestUrl,String manaType) {
        String listUrl = "http://credit.customs.gov.cn/ccppserver/ccpp/queryList";
        String bodyParams = "{\"manaType\":\""+manaType+"\",\"apanage\":\"610000\",\"depCodeChg\":\"\",\"curPage\":\"1\",\"pageSize\":20}";
        String result = HttpService.sendHttp(listUrl,"post",null,bodyParams,"json");
        JSONObject data = getDatas(result);
        if(null == data){
            return ;
        }
        int totalCount =0;
        if(data.containsKey("totalCount")){
            totalCount = Integer.parseInt(data.getString("totalCount"));
        }
        JSONObject detail = new JSONObject();
        detail.put("queryType","0");
        detail.put("curPage",1);
        detail.put("pageSize",10);
        String serverUrl = getRequestUrl("");
        if (StrUtil.isNull(serverUrl)) {
            log.warn("RECEIVE-SERVER服务已下线");
            return;
        }
        int pageCount = 0;
        if (totalCount % 20 != 0) {
            pageCount++;
        }
        int pageNo = 1;
        String detailUrl = serverUrl +(requestUrl.startsWith("/receive") ? requestUrl : "receive" + requestUrl);
        detailUrl = detailUrl.replaceAll("/receive/receive/","/receive/");
        do{
            JSONArray arrays = data.getJSONArray("copInfoList");
            for(int i=0;i<arrays.size();i++) {
                JSONObject obj = arrays.getJSONObject(i);
                detail.put("seqNo",obj.getString("seqNo"));
                detail.put("saicSysNo",obj.getString("saicSysNo"));
                String resData = HttpService.sendHttp(detailUrl,"post",null,detail.toJSONString(),"json");
            }
            if(pageNo < pageCount){
                data = null;
                try {
                    Thread.sleep(60000l);
                } catch (InterruptedException e) {
                }
                pageNo++;
                bodyParams = "{\"manaType\":\""+manaType+"\",\"apanage\":\"610000\",\"depCodeChg\":\"\",\"curPage\":\""+pageNo+"\",\"pageSize\":20}";
                result = HttpService.sendHttp(listUrl,"post",null,bodyParams,"json");
                data = getDatas(result);
                if(null == data){
                    pageNo = pageCount+1;
                }
            }
        } while(pageNo > pageCount);
    }

    private JSONObject getDatas(String result){
        if(StrUtil.isNull(result)){
            return null;
        }
        result = ScriptEngineUtil.getInstance().decryptCreditCustoms(result);
        JSONObject resultData = JSON.parseObject(result);
        if("true".equals(resultData.getString("ok")) && resultData.containsKey("data")){
            JSONObject data = resultData.getJSONObject("data");
            if(data.containsKey("copInfoList")){
                return data;
            }
        }
        return null;
    }

    private List<Map> select(String dataSource,String sql){
        try{
            Connection con = ConnctionData.getInstance().getConnection(dataSource);
            return ConnctionData.getInstance().selectListInfo(con, sql);
        }catch (SQLException e){
            throw new BusinessException(e.getMessage());
        }
    }
}
